package org.jeecg.modules.car.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.StringUtils;
import org.jeecg.common.util.wx.WXPayUtil;
import org.jeecg.config.GetRequestJsonUtils;
import org.jeecg.config.JsonMapper;
import org.jeecg.config.Sm4Util;
import org.jeecg.entity.car.CarDerateDetails;
import org.jeecg.entity.car.CarMerchantDerate;
import org.jeecg.entity.car.CarOrder;
import org.jeecg.entity.car.CarParkingRecord;
import org.jeecg.enums.PayModeEnum;
import org.jeecg.enums.PayStatusEnum;
import org.jeecg.enums.car.CarDerateDetailStatusEnum;
import org.jeecg.enums.car.CarDerateStatusEnum;
import org.jeecg.enums.car.CarOrderTypeEnum;
import org.jeecg.enums.car.CarSyncStatusEnum;
import org.jeecg.enums.common.PayTypeEnum;
import org.jeecg.modules.car.entity.CarParkInfo;
import org.jeecg.modules.car.entity.CarPayNotify;
import org.jeecg.modules.car.service.*;
import org.jeecg.modules.car.service.impl.ForeignCarJGSService;
import org.jeecg.modules.car.service.impl.ForeignCarShParkingService;
import org.jeecg.modules.car.service.impl.SyncCarServiceImpl;
import org.jeecg.vo.car.ForeignCarIotPayTempReq;
import org.jeecg.vo.car.ForeignCarPayReq;
import org.jeecg.vo.car.ForeignCarTempCostResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 车禁充值账单 - 对外接口
 *
 * @author liurui
 * @version v1.0
 * @date 2020年09月27日
 */
@Slf4j
@RestController
@RequestMapping(value = "/b/foreign/carOrder")
public class ForeignCarOrderController {
    @Autowired
    private ICarOrderService carOrderService;
    @Autowired
    private ForeignCarJGSService foreignCarJGSService;
    @Autowired
    private ICarParkingRecordService carParkingRecordService;
    @Autowired
    private ICarMerchantDerateService carMerchantDerateService;
    @Autowired
    private ICarParkInfoService carParkInfoService;
    @Autowired
    private SyncCarServiceImpl syncCarService;
    @Autowired
    private ICarDerateDetailsService derateDetailsService;
    @Autowired
    private ForeignCarShParkingService shParkingService;

    @Value("${pay.fftEncryptKey}")
    private String fftEncryptKey; //付费通加密key

    /**
     * 车辆临停生成订单接口
     * @return
     */
    @AutoLog(value = "车辆临停支付接口")
    @ApiOperation(value="车辆临停支付接口", notes="车辆临停支付接口")
    @GetMapping(value = "/pay")
    public Result pay(ForeignCarPayReq payReq, HttpServletRequest req){
        try{
            log.info("车辆临停支付接口请求数据:{}", payReq);
            if (StringUtils.isNotBlank(payReq.getRecordId())){
                CarParkingRecord record = carParkingRecordService.getByRecordId(payReq.getRecordId(),1);
                if (record == null){
                    return Result.error("车辆已出场，请勿重复支付！");
                }
            }
            CarParkInfo carPark =  carParkInfoService.getByOutParkId(payReq.getOutParkId());
            if (carPark == null) return Result.error("车场未设置！");
            if (payReq.getUpayFee() == null || payReq.getUpayFee().compareTo(BigDecimal.ZERO) <0){
                return  Result.error("支付金额需大于0元！");
            }
            //创建支付订单
            CarOrder carOrder = new CarOrder();
            carOrder.setId(String.valueOf(IdWorker.getId()));
            carOrder.setUserMobile(payReq.getMobile());
            carOrder.setTenantId(carPark.getTenantId());
            carOrder.setProjectId(carPark.getProjectId());
            carOrder.setPayMode(PayModeEnum.PAY_MODE_WECHAT.getCode());
            carOrder.setCarTypeName("临停车");
            carOrder.setOrderType(CarOrderTypeEnum.ORDER_TYPE_TEMP.getCode());
            carOrder.setSyncStatus(CarSyncStatusEnum.SYNC_STATUS_NO.getCode());
            if (payReq.getUpayFee().compareTo(BigDecimal.ZERO) == 0){
                carOrder.setPayStatus(PayStatusEnum.PAY_STATUS_YES.getCode());
            } else {
                carOrder.setPayStatus(PayStatusEnum.PAY_STATUS_NO.getCode());
            }
            carOrder.setCheckStatus(1);
            carOrder.setPayTime(new Date());
            if (PayModeEnum.PAY_MODE_WEIXINPAY.getCode().equals(payReq.getPayMode())){
                carOrder.setPayType(PayTypeEnum.PAY_METHOD_WEIXINPAY.getCode().toString());
            }else if (PayModeEnum.PAY_MODE_ALIPAY.getCode().equals(payReq.getPayMode())){
                carOrder.setPayType(PayTypeEnum.PAY_METHOD_ALIPAY.getCode().toString());
            }
            carOrder.setPayAmount(payReq.getUpayFee());
            carOrder.setPayDue(payReq.getTotalFee());
            carOrder.setPayReduced(payReq.getDiscountFee());
            carOrder.setSn(payReq.getSn());
            carOrder.setCarNo(payReq.getPlateNumber());
            carOrder.setRequest(payReq.getJsonString());
            carOrder.setOrderNo(payReq.getOrderNo());
            carOrder.setTransNo(payReq.getTransNo());
            carOrder.setResponse(payReq.getResponse());
            carOrder.setDerateId(payReq.getDerateId());
            carOrder.setDerateDetailId(payReq.getDerateDetailId());
            carOrder.setParkId(carPark.getId());
            //公众号支付目标只支持FFT
//            carOrder.setPayChannel("FFT");
            carOrder.setPayChannel(payReq.getChannel());
            log.info("临停缴费插入的订单信息:{}",carOrder);
            carOrderService.save(carOrder);
            //支付金额等于0的情况
            if (payReq.getUpayFee().compareTo(BigDecimal.ZERO) == 0){
                try{
                    //需要通知车禁进行开闸
                    ForeignCarIotPayTempReq carPayTempReq = new ForeignCarIotPayTempReq();
                    carPayTempReq.setOrder_id(payReq.getSn());
                    carPayTempReq.setOrder_no(payReq.getOrderNo());
                    carPayTempReq.setPark_id(payReq.getOutParkId());
                    carPayTempReq.setPay_fee(payReq.getTotalFee().toString());
                    carPayTempReq.setPlate_number(payReq.getPlateNumber());
                    carPayTempReq.setPay_type("2");
                    Result<String> tempCostRes = foreignCarJGSService.payTempCost(carPayTempReq);
                    if (tempCostRes.isSuccess()){
                        carOrderService.updateSyncStatus(carOrder.getId(),CarSyncStatusEnum.SYNC_STATUS_YES.getCode(), null);
                    } else {
                        log.error("出口处扫码通知开闸失败:{}",tempCostRes.getMessage());
                    }
                    if (StringUtils.isNotBlank(payReq.getDerateId()) && StringUtils.isNotBlank(payReq.getPlateNumber())){
                        //更新优惠券绑定车牌状态为已使用
                        CarDerateDetails derateDetails = derateDetailsService.getDerateDetail(payReq.getPlateNumber());
                        derateDetails.setStatus(CarDerateDetailStatusEnum.CAR_DERATE_DETAIL_STATUS_1.getCode());
                        derateDetails.setUseTime(new Date());
                        derateDetailsService.updateById(derateDetails);
                    }
                }catch (Exception e){
                    log.error("出口处扫码通知开闸异常:{}",e);
                }
            } else {
                if ("FFT".equals(payReq.getChannel())){
                    //异步查询支付状态
                    syncCarService.queryTempPayResult(payReq.getTransNo());
                }
            }
            return Result.ok("支付成功");
        }catch (Exception e){
            log.error("生成订单信息异常:{}",e);
            return Result.error("处理异常");
        }
    }

    @AutoLog(value = "无牌车入口处扫码")
    @ApiOperation(value="无牌车入口处扫码", notes="无牌车入口处扫码")
    @GetMapping(value = "/noPlateEntrance")
    public Result<ForeignCarTempCostResp> noPlateEntrance(@ApiParam(value = "外部车场id",required = true) String outParkId,
                                                          @ApiParam(value = "通道id",required = true) String gateId,
                                                          @ApiParam(value = "微信/支付宝OpenID",required = true) String openId){
        try{
            log.info("无牌车入口处扫码接收参数:outParkId={},gateId={},openId={}",outParkId,gateId,openId);
            Result<ForeignCarTempCostResp> respResult = foreignCarJGSService.noPlateQRcode(outParkId,gateId,openId);
            return respResult;
        }catch (Exception e){
            log.error("无牌车入口处扫码异常：{}",e);
            return Result.error("系统繁忙！");
        }
    }

    /**
     *   获取车辆临停缴费信息 - 用于无牌车扫码进出、有牌车通道口扫码缴费
     * @param outParkId
     * @param gateId
     * @param openId
     * @return
     */
    @AutoLog(value = "获取车辆临停缴费信息-出口处扫码")
    @ApiOperation(value="获取车辆临停缴费信息-出口处扫码", notes="获取车辆临停缴费信息-出口处扫码")
    @GetMapping(value = "/getCarPayDetailsNoPlate")
    public Result<ForeignCarTempCostResp> getCarPayDetailsNoPlate(@ApiParam(value = "外部车场id",required = true) String outParkId,
                                                                  @ApiParam(value = "通道id",required = true) String gateId,
                                                                  @ApiParam(value = "微信/支付宝OpenID",required = false) String openId){
        try {
            if (StringUtils.isBlank(openId)) openId = StringUtils.createSn("code", 3);
            Result<ForeignCarTempCostResp> respResult = foreignCarJGSService.noPlateQRcode(outParkId,gateId,openId);
            if (respResult.isSuccess()){
                CarParkInfo carParkInfo = carParkInfoService.getByOutParkId(outParkId);
                if (carParkInfo == null){
                    return Result.error("车场尚未开通扫码接口");
                }
                ForeignCarTempCostResp  tempCostResp =  respResult.getResult();
                tempCostResp.setOut_park_id(outParkId);
                tempCostResp.setPark_id(carParkInfo.getId());
                String plate  = tempCostResp.getPlate_number();
                //查询车辆是否有手动打折优惠的情况
                CarDerateDetails derateDetails = derateDetailsService.getDerateDetail(plate);
//                CarMerchantDerate carMerchantDerate = carMerchantDerateService.getByPlateStatus(plate,CarDerateStatusEnum.CAR_DERATE_STATUS_1.getCode());
                BigDecimal derateAmount = BigDecimal.ZERO;
                BigDecimal totalFee = StringUtils.isNotBlank(tempCostResp.getTotal_fee())? new BigDecimal(tempCostResp.getTotal_fee()):BigDecimal.ZERO;
                if (derateDetails != null ){  //有优惠
                    derateAmount = derateDetails.getDerateAmount();//优惠金额
                    BigDecimal upayFee = totalFee.subtract(derateAmount); //减免后的应缴金额
                    if (upayFee.compareTo(BigDecimal.ZERO) < 0 ) upayFee = BigDecimal.ZERO;  //负数金额显示0元
                    tempCostResp.setDiscount_fee(derateAmount.toString());
                    tempCostResp.setUpay_fee(upayFee.toString());
                    tempCostResp.setDerate_id(derateDetails.getDerateId()); //返回优惠券id - 即时减免的
                    tempCostResp.setDerate_detail_id(derateDetails.getId()); //优惠券明细id
                }
                String inTime = tempCostResp.getIn_time();
                if (inTime != null){
                    Date inTimeDate = DateUtils.str2Date(inTime,DateUtils.datetimeFormat);
                    tempCostResp.setIn_time(DateUtils.date2Str(inTimeDate,DateUtils.datetimeFormat));
                    Date outDate = new Date();
                    String count  =  DateUtils.getDatePoor(outDate,inTimeDate);
                    tempCostResp.setStop_time(count);
                    //市公众平台减免 - 无入场时间 或 已经优惠的  不重复优惠
                    if (StringUtils.isNotBlank(carParkInfo.getSuperviseParkingId()) && derateAmount.compareTo(BigDecimal.ZERO) <= 0){
                        BigDecimal reduceAmount = shParkingService.reduces(carParkInfo,plate,inTimeDate);
                        BigDecimal upayFee = totalFee.subtract(reduceAmount); //减免后的应缴金额
                        tempCostResp.setDiscount_fee(reduceAmount.toString());
                        tempCostResp.setUpay_fee(upayFee.toString());
                    }
                }
                return Result.ok(tempCostResp);
            } else {
                return respResult;
            }
        }catch (Exception e){
            log.error("获取车辆临停缴费信息-出口处扫码异常：{}",e);
            return Result.error("系统繁忙！");
        }
    }


    /**
     *  获取车辆临停缴费信息 - 寻车缴费、车主扫打折二维码
     * @return
     */
    @AutoLog(value = "获取车辆临停缴费信息")
    @ApiOperation(value="获取车辆临停缴费信息", notes="获取车辆临停缴费信息")
    @GetMapping(value = "/getCarPayDetails")
    public Result<ForeignCarTempCostResp> getCarPayDetails(@ApiParam(value = "车牌号",required = true) String plate,
                                                           @ApiParam(value = "优惠券id",required = false) String derateId,
                                                           HttpServletRequest req){
        try{
            log.info("获取车辆临停缴费信息请求数据:车牌{},优惠券{}",plate,derateId);
            CarParkingRecord carParkingRecord =  carParkingRecordService.getParkingRecordByCarNo(plate);
            log.info("进出记录数据:{}",carParkingRecord);
            if(carParkingRecord != null && StringUtils.isNotEmpty(carParkingRecord.getRecordId())){
                Result<ForeignCarTempCostResp>  foreignCarTempCostRespResult =  foreignCarJGSService.calculatingTempCost(carParkingRecord.getRecordId(),carParkingRecord.getOutParkId(),plate);
//                if ("199".equals(carParkingRecord.getParkId())){  //测完代码
//                    ForeignCarTempCostResp costResp = new ForeignCarTempCostResp();
//                    costResp.setRecord_id(carParkingRecord.getRecordId());
//                    costResp.setTotal_fee("0.01");
//                    costResp.setUpay_fee("0.01");
//                    costResp.setDiscount_fee("0");
//                    costResp.setIn_time(DateUtils.date2Str(carParkingRecord.getEntranceTime(),DateUtils.datetimeFormat));
//                    costResp.setPlate_number(carParkingRecord.getCarNo());
//                    costResp.setPark_id(carParkingRecord.getOutParkId());
////                    costResp.setOut_park_id(carParkingRecord.getOutParkId());
//                    foreignCarTempCostRespResult = Result.ok(costResp);
//                }
                if (foreignCarTempCostRespResult.isSuccess()){
                    ForeignCarTempCostResp tempCostResp = foreignCarTempCostRespResult.getResult();
                    tempCostResp.setOut_park_id(tempCostResp.getPark_id());
                    tempCostResp.setPark_id(carParkingRecord.getParkId());
                    String inTime = tempCostResp.getIn_time();
                    if (inTime != null){
                        Date inTimeDate = DateUtils.str2Date(inTime,DateUtils.datetimeFormat);
                        tempCostResp.setIn_time(DateUtils.date2Str(inTimeDate,DateUtils.datetimeFormat));
                        Date outDate = new Date();
                        String count  =  DateUtils.getDatePoor(outDate,inTimeDate);
                        tempCostResp.setStop_time(count);
                    }
                    if (StringUtils.isNotBlank(derateId)){  //扫优惠二维码
                        //判断车牌是否已经绑定优惠信息
                        CarDerateDetails derateDetails = derateDetailsService.getDerateDetail(plate);
                        if (derateDetails == null){
                            CarMerchantDerate carMerchantDerate = carMerchantDerateService.getById(derateId);
                            if (carMerchantDerate == null){
                                return Result.error("优惠券不存在！");
                            }
                            if (carMerchantDerate.getEndTime() != null && carMerchantDerate.getEndTime().compareTo(new Date()) <= 0){
                                return Result.error("优惠券已过有效期！");
                            }
                            if (CarDerateStatusEnum.CAR_DERATE_STATUS_2.getCode().equals(carMerchantDerate.getStatus())){
                                return Result.error("优惠券已被使用！");
                            }
                            //添加优惠卷明细业务
                            Result<String> detailsRes = derateDetailsService.addDetails(carMerchantDerate, plate);
                            if (!detailsRes.isSuccess()){
                                return Result.error("优惠券处理繁忙");
                            }
                            tempCostResp.setDiscount_fee(carMerchantDerate.getDerateAmount().toString());
                            BigDecimal totalFee  = StringUtils.isNotBlank(tempCostResp.getTotal_fee())? new BigDecimal(tempCostResp.getTotal_fee()):BigDecimal.ZERO;
                            BigDecimal upayFee = totalFee.subtract(carMerchantDerate.getDerateAmount());
                            if (upayFee.compareTo(BigDecimal.ZERO) <= 0 ) {
                                upayFee = BigDecimal.ZERO; //需缴金额设置为0元,不显示负数
                            }
                            tempCostResp.setUpay_fee(upayFee.toString());
                            tempCostResp.setDerate_id(derateId);
                            tempCostResp.setDerate_detail_id(detailsRes.getMessage());
                        }else {
                            //已绑定时优惠信息从绑定明细表中获取，防止优惠卷被删除无法获取优惠信息
                            tempCostResp.setDiscount_fee(derateDetails.getDerateAmount().toString());
                            BigDecimal totalFee  = StringUtils.isNotBlank(tempCostResp.getTotal_fee())? new BigDecimal(tempCostResp.getTotal_fee()):BigDecimal.ZERO;
                            BigDecimal upayFee = totalFee.subtract(derateDetails.getDerateAmount());
                            if (upayFee.compareTo(BigDecimal.ZERO) <= 0 ) {
                                upayFee = BigDecimal.ZERO; //需缴金额设置为0元,不显示负数
                            }
                            tempCostResp.setUpay_fee(upayFee.toString());
                            tempCostResp.setDerate_id(derateDetails.getDerateId());
                            tempCostResp.setDerate_detail_id(derateDetails.getId());
                        }
                    } else {
                        //判断车牌是否已经绑定优惠信息
                        CarDerateDetails derateDetails = derateDetailsService.getDerateDetail(plate);
                        if (derateDetails != null){
                            BigDecimal derateAmount =  derateDetails.getDerateAmount();
                            BigDecimal totalFee =  StringUtils.isNotBlank(tempCostResp.getTotal_fee())? new BigDecimal(tempCostResp.getTotal_fee()):BigDecimal.ZERO;
                            BigDecimal upayFee = totalFee.subtract(derateAmount); //减免后的应缴金额
                            if (upayFee.compareTo(BigDecimal.ZERO) < 0 ) upayFee = BigDecimal.ZERO;  //负数金额显示0元
                            tempCostResp.setDiscount_fee(derateAmount.toString());
                            tempCostResp.setUpay_fee(upayFee.toString());
                            tempCostResp.setDerate_id(derateDetails.getDerateId());
                            tempCostResp.setDerate_detail_id(derateDetails.getId());
                        }
                    }
                    return Result.ok(tempCostResp);
                } else {
                    if (null != foreignCarTempCostRespResult.getMessage() && foreignCarTempCostRespResult.getMessage().equals("不需要缴费")){
                        foreignCarTempCostRespResult.setMessage("车辆未产生费用，如需减免请使用二维码减免");
                    }
                    return foreignCarTempCostRespResult;
                }
            }else{
                return Result.error("车场没有"+plate+"该车辆信息，请重新查询！");
            }
        }catch (Exception e){
            log.error("获取车辆临停缴费信息异常:{}",e);
            return Result.error("处理异常");
        }
    }

    /**
     * 回调地址
     *
     * @return
     */
    @RequestMapping(value = "/carPayNotify", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation("付费通回调接口")
    public String carPayNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            JSONObject jsonObject = GetRequestJsonUtils.getRequestJsonObject(request,fftEncryptKey);
            log.info("付费通回调接口参数：{}",jsonObject);
            CarPayNotify stu= JSON.parseObject(jsonObject.toJSONString(), CarPayNotify.class);
            Result<CarOrder> result = carOrderService.carPayNotify(stu);
            return Sm4Util.encryptEcb(fftEncryptKey,"200success");
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return Sm4Util.encryptEcb(fftEncryptKey,"error");
    }

    /**
     * 光大回调
     *
     * @return
     */
    @RequestMapping(value = "/carPayCEBNotify")
    @ResponseBody
    @ApiOperation("光大回调接口")
    public void carPayCEBNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            BufferedReader reader = request.getReader();
            String json = reader.readLine();
            log.info("光大月卡车回调数据:{}", json);
            reader.close();
            net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(json);
            int code = jsonObject.getInt("code");
            int status = jsonObject.getInt("status");
            net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(jsonObject.getString("data"));
            if (code == 0){
                CarPayNotify stu = new CarPayNotify();
                stu.setOrderId(data.getString("out_trade_no"));
                stu.setPaymentAmt(data.getString("amount"));
                stu.setPaymentTime(data.getString("payment_at"));
                stu.setTransNo(data.getString("transaction_number"));
                Result<CarOrder> result = carOrderService.carPayNotify(stu);
            }
            Writer out = response.getWriter();
            Map<String, Object> map = new HashMap<String, Object>();
            if (code == 0 && status == 0) {
                map.put("status", 0);
                map.put("msg", "");
                map.put("code", 0);
            } else {
                map.put("status", 1);
                map.put("msg", "");
                map.put("code", 0);
            }
            out.write(JsonMapper.getInstance().toJson(map));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @PostMapping("/carPayWXNPNotify")
    @ApiOperation("服务商微信支付回调")
    @ResponseBody
    public String carPayWXNPNotify(HttpServletRequest request) throws Exception{
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultXml = new String(outSteam.toByteArray(), "utf-8");
        log.info("服务商微信支付回调XML文件====="+resultXml);
        Map<String, String> params = WXPayUtil.xmlToMap(resultXml);
        outSteam.close();
        inStream.close();
        log.info("服务商微信支付回调参数======"+params.toString());
        Map<String,String> return_data = new HashMap<String,String>();
        if ("SUCCESS".equals(params.get("result_code"))){
            CarPayNotify stu = new CarPayNotify();
            stu.setOrderId(params.get("out_trade_no"));
            stu.setPaymentAmt(String.valueOf(Double.valueOf(params.get("total_fee"))/100));
            stu.setPaymentTime(params.get("time_end"));
            stu.setTransNo(params.get("transaction_id"));
            Result<CarOrder> result = carOrderService.carPayNotify(stu);
            return_data.put("return_code", "SUCCESS");
            return_data.put("return_msg", "OK");
        }else {
            return_data.put("return_code", "FAIL");
            return_data.put("return_msg", "return_code不正确");
        }
        return WXPayUtil.mapToXml(return_data);
    }



}